import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Action, Store } from '@ngrx/store';
import { Actions, Effect } from '@ngrx/effects';
import {
    ProjectActionTypes,
    ProjectLoadSuccessAction,
    ProjectLoadFailAction,
    ProjectAddSuccessAction,
    ProjectAddFailAction,
    ProjectUpdateSuccessAction,
    ProjectUpdateFailAction,
    ProjectDeleteSuccessAction,
    ProjectDeleteFailAction,
    ProjectInviteSuccessAction,
    ProjectInviteFailAction
} from '../actions/projects.action';
import { ProjectService } from '../services/project.service';
import { toPayload } from '@ngrx/effects/src/util';
import * as fromRoot from '../reducers';
import { Router } from '@angular/router';
import { TaskListLoadAction } from '../actions/task-list.action';
import { Project } from '../domain/index';
import { UserLoadAction, UserAddAction, UserDeleteAction, UserUpdateAction } from '../actions/user.action';
@Injectable()
export class ProjectEffects {
    @Effect()
    loadProjects$: Observable<Action> = this.actions$
        .ofType(ProjectActionTypes.LOAD)
        .map(toPayload)
        .withLatestFrom(this.store$.select(fromRoot.getAuthState))
        .switchMap(([_, auth]) => this.service$.get(auth.user.id)
            .map(projects => new ProjectLoadSuccessAction(projects))
            .catch(err => Observable.of(new ProjectLoadFailAction(JSON.stringify(err)))));
    @Effect()
    addProjects$: Observable<Action> = this.actions$
        .ofType(ProjectActionTypes.ADD)
        .map(toPayload)
        .debug('add')
        .withLatestFrom(this.store$.select(fromRoot.getAuthState).map(auth => auth.user))
        .switchMap(([project, user]) => {
            const added = { ...project, members: [`${user.id}`] };
            return this.service$.add(added)
                .map(prj => new ProjectAddSuccessAction(prj))
                .catch(err => Observable.of(new ProjectAddFailAction(JSON.stringify(err))));
        });

    @Effect()
    updateProjects$: Observable<Action> = this.actions$
        .ofType(ProjectActionTypes.UPDATE)
        .map(toPayload)
        .switchMap((project) => this.service$.update(project)
            .map(prj => new ProjectUpdateSuccessAction(prj))
            .catch(err => Observable.of(new ProjectUpdateFailAction(JSON.stringify(err)))));
    @Effect()
    delProjects$: Observable<Action> = this.actions$
        .ofType(ProjectActionTypes.DELETE)
        .map(toPayload)
        .switchMap((project) => this.service$.del(project)
            .map(prj => new ProjectDeleteSuccessAction(prj))
            .catch(err => Observable.of(new ProjectDeleteFailAction(JSON.stringify(err)))));

    // @Effect()
    // selectProjects$: Observable<Action> = this.actions$
    //     .ofType(ProjectActionTypes.SELECT_PROJECT)
    //     .map(toPayload)
    //     .map(project => {
    //          this.router.navigate([`/tasklists/${project.id}`]);
    //         return null;
    //     });
    @Effect()
    loadTaskList$: Observable<Action> = this.actions$
        .ofType(ProjectActionTypes.SELECT_PROJECT)
        .map(toPayload)
        .map(project => new TaskListLoadAction(project.id));

    @Effect()
    invite$: Observable<Action> = this.actions$
        .ofType(ProjectActionTypes.INVITE)
        .map(toPayload)
        .switchMap(({ projectId, members }) => this.service$.invite(projectId, members)
            .map(prj => new ProjectInviteSuccessAction(prj))
            .catch(err => Observable.of(new ProjectInviteFailAction(JSON.stringify(err)))));

    @Effect()
    loadUsers$: Observable<Action> = this.actions$
        .ofType(ProjectActionTypes.LOAD_SUCCESS)
        .map(toPayload)
        .switchMap((projects: Project[]) => Observable.from(projects.map(prj => prj.id)))
        .map(projectId => new UserLoadAction(projectId));

    @Effect()
    addUsersProjects$: Observable<Action> = this.actions$
        .ofType(ProjectActionTypes.ADD_SUCCESS)
        .map(toPayload)
        .map(project => project.id)
        .withLatestFrom(this.store$.select(fromRoot.getAuthState).map(auth => auth.user), (projectId, user) => {
            return new UserAddAction({ user: user, projectId: projectId });
        });
    @Effect()
    removeUsersProject$: Observable<Action> = this.actions$
        .ofType(ProjectActionTypes.DELETE_SUCCESS)
        .map(toPayload)
        .map(project => project.id)
        .withLatestFrom(this.store$.select(fromRoot.getAuthState).map(auth => auth.user), (projectId, user) => {
            return new UserDeleteAction({ user: user, projectId: projectId });
        });
    @Effect()
    updateUsersProject$: Observable<Action> = this.actions$
        .ofType(ProjectActionTypes.INVITE_SUCCESS)
        .map(toPayload)
        .map(project => new UserUpdateAction(project));
    constructor(
        private actions$: Actions,
        private service$: ProjectService,
        private store$: Store<fromRoot.State>,
        private router: Router
    ) { }
}
